#include "threadPool.h"

enum operation{
    //0~10特殊操作，错误返回之类的
    //11~20目录操作
    //21~30文件操作
    //31~40SQL操作
    //一些名字加了下划线是因为某一部分单独是关键字

    return_result=2,

    cd_oreder=11,
    pwd_der=13,

    puts_file=21,
    file_hash=22,
    file_name=23,
    cur_size=24,
    gets_file=25,
    remove_file=26,
    dont_send=27,
    go_send=28,
    file_txt=29,

    salt=31,
    login=33
};

int init_train(train_t *train){
    train->type=0;
    train->length=0;
    size_t size=sizeof(train->arr);
    bzero(train->arr,size);
    return 0;
}
int recv_train(int netfd,train_t *train){
    init_train(train);
    recv(netfd,&train->type,sizeof(train->type),0);
    recv(netfd,&train->length,sizeof(train->length),0);
    recv(netfd,train->arr,train->length,0);
    return 0;
}

int init_file_msg(file_msg_t *msg){
    msg->fd=-1;
    msg->transed_byte=0;
    bzero(msg->filename,sizeof(msg->filename));
    bzero(msg->hash_file,sizeof(msg->hash_file));
    return 0;
}

//int com_hash(MYSQL *mysql,file_msg_t *file_message){
//    char sql[]="select * from catalog where md5=";
//    strcat(sql,file_message->hash_file);
//    mysql_query(mysql,sql);
//    printf("sql = %s\n",sql);
//    MYSQL_RES *res=mysql_store_result(mysql);
//    if (!res) {
//    fprintf(stderr, "mysql_store_result failed: %s\n", mysql_error(mysql));
//
//    return 0;
//}
//    printf("uuuu\n");
//    unsigned long exist=mysql_num_rows(res);
//    printf("beforeif\n");
//    if(exist>0){
//    printf("exit: %lu\n",exist);
//        return 1;
//    }
//    else{
//    printf("exit: %lu\n",exist);
//        return 0 ;
//    }
//}
int com_hash(MYSQL *mysql, file_msg_t *file_message){
    char sql[256] = {0};
    snprintf(sql, sizeof(sql), "select 1 from catalog where md5='%s'", file_message->hash_file);
    printf("sql = %s\n", sql);

    if(mysql_query(mysql, sql)) {
        fprintf(stderr, "SQL query failed: %s\n", mysql_error(mysql));
        return 0;
    }

    MYSQL_RES *res = mysql_store_result(mysql);
    if (!res) {
        fprintf(stderr, "mysql_store_result failed: %s\n", mysql_error(mysql));
        return 0;
    }

    unsigned long exist = mysql_num_rows(res);
    printf("exist: %lu\n", exist);

    mysql_free_result(res);
    return exist > 0 ? 1 : 0;
}


int insert_filetable(MYSQL *mysql,file_msg_t *file_message,char *user,Link_list_t *catalog,int flags){
    char sql_s[4096]={0};
    char sql_i[4096]={0};
    if(flags==1){//已有文件直接做连接

        sprintf(sql_s,"select * from  catalog where md5= '%s'",file_message->hash_file);
        mysql_query(mysql,sql_s);
        MYSQL_RES *res=mysql_store_result(mysql);
        MYSQL_ROW row = mysql_fetch_row(res);
        sprintf(sql_i,"insert into catalog (filename, user, parent_id, md5, type, path) values ('%s','%s','%s','%s''%s','%s')",file_message->filename,user,row[4],row[5],row[6],row[7]);
        mysql_query(mysql,sql_i);
        mysql_free_result(res);
        return 0;
    }
    else if(flags==2){
        char path[1024]={0};
        pwd_order(catalog,mysql,path);
        printf("%s\n",path);
        int len = sizeof(file_message->filename);
        printf("%d\n",len);
        printf("filename: %s\n",file_message->filename);
        printf("user:%s\n",user);
        printf("%d\n",catalog->tail->id);
        printf("%s\n",file_message->hash_file);
        printf("%s\n",path);
        sprintf(sql_i,"insert into catalog (filename, user, parent_id, md5, type, path) values ('%s','%s','%d','%s',NULL,'%s')",file_message->filename,user,catalog->tail->id,file_message->hash_file,path);
        printf("sql_i: %s\n",sql_i);
        int qret = mysql_query(mysql,sql_i);
        if (qret != 0) {
            fprintf(stderr, "mysql_query_mkdir failed: %s\n", mysql_error(mysql));
            return -1;
        }

        return 0;
    }
    return 0;
}

int recv_file(int netfd,MYSQL *mysql,Link_list_t *catalog,char user[]){
    printf("000\n");
    train_t train;
    init_train(&train);
    file_msg_t file_mes;
    init_file_msg(&file_mes);
    printf("aaa\n");
    recv_train(netfd,&train);
    strcpy(file_mes.filename,train.arr);

    recv_train(netfd,&train);
    strcpy(file_mes.hash_file,train.arr);
    //
    //
    printf("bbb\n");
    int ret=com_hash(mysql,&file_mes);//判断hash
    printf("YYY\n");
    if(ret==1){//已经有这个文件,偷懒做链接就行
        insert_filetable(mysql,&file_mes,user,catalog,1);
        printf("iiiii\n");
        init_train(&train);
        train.type=dont_send;
        train.length=0;
        send(netfd,&train,sizeof(train.type)+sizeof(train.length)+train.length,0);
        return 0;
    }
    else if(ret==0){//乖乖收吧!
        insert_filetable(mysql,&file_mes,user,catalog,2);
        init_train(&train);
        train.type=go_send;
        train.length=0;
        printf("ccc\n");
        send(netfd,&train,sizeof(train.type)+sizeof(train.length)+train.length,0);
        printf("LLL\n");
    }

    char path[1024]={0};

    pwd_order(catalog,mysql,path);

    file_mes.fd=open(path,O_CREAT|O_WRONLY,0766);
    printf("MMM\n");
    while(1){//开始循环接收小火车
        init_train(&train);
        recv_train(netfd,&train);
        write(file_mes.fd,train.arr,train.length);

        if(train.length==0){//收到空的TLV结构体,接收完毕
            break;
        }
    }
    close(file_mes.fd);
    return 0;
}

int caculate_hash(char *filepath,char *sha){
    EVP_MD_CTX *ctx=EVP_MD_CTX_new();
    if(!ctx) return -1;

    unsigned char temp[32]={0};
    const EVP_MD *algorithm=EVP_sha256();
    unsigned int hash_length=32;

    EVP_DigestInit_ex(ctx,algorithm,NULL);
    char buf[4096]={0};

    int fd=open(filepath,O_RDWR);
    while(1){
        bzero(buf,sizeof(buf));
        ssize_t ret=read(fd,buf,sizeof(buf));
        EVP_DigestUpdate(ctx,buf,ret);
        if(ret==0)   break;
    }

    EVP_DigestFinal_ex(ctx,temp,&hash_length);
    for (int i = 0; i < 32; i++) {
        sprintf(sha + i*2, "%02x", temp[i]);
    }

    close(fd);
    EVP_MD_CTX_free(ctx);

    return 0;
}
int push_file(int netfd,char *filename,char* user,MYSQL *mysql,Link_list_t *catalog){
    printf("000\n");
    check_name_exists(mysql, user, catalog->tail->id, filename);

    printf("aaaa\n");
    char sql[1024];
    sprintf(sql,"select md5 from catalog where filename= '%s' and parent_id = '%d'",filename,catalog->tail->id);
    mysql_query(mysql,sql);
    MYSQL_RES *res = mysql_store_result(mysql);
    MYSQL_ROW row;
    row=mysql_fetch_row(res);//get hash of target file
    char filename_t[64]={0};
    strcpy(filename_t,row[0]);
    printf("bbb\n");
    train_t train;
    init_train(&train);
    file_msg_t file_mes;
    init_file_msg(&file_mes);
    printf("ccc\n");
    recv_train(netfd,&train);
    strcpy(file_mes.filename,train.arr);

    recv(netfd,&train.type,sizeof(train.type),0);
    if(train.type!=cur_size){
        fprintf(stderr,"TLV type is not cur_size");
    }
    recv(netfd,&train.length,sizeof(train.length),0);
    file_mes.transed_byte=train.length;
    printf("ddd\n");
    int fd=open(filename_t,O_RDWR);
    lseek(fd, file_mes.transed_byte, SEEK_SET);

    while(1){
        init_train(&train);
        train.type=file_txt;
        ssize_t ret=read(fd,train.arr,sizeof(train.arr));
        train.length=ret;
        send(netfd,&train,sizeof(train.type)+sizeof(train.length)+train.length,0);

        if(ret==0){
            break;
        }
    }
    printf("zzz\n");
    close(fd);
    return 0;
}
